package com.kaikeba.estack.web;

import com.kaikeba.estack.bean.User;
import com.kaikeba.estack.common.util.BeanUtil;
import com.kaikeba.estack.common.util.JSONUtil;
import com.kaikeba.estack.web.constant.WebConstant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.ConcurrentSkipListSet;

/**
 * 权限相关的工具类
 *
 * @Auth xingwan
 * @Date 2020/9/12 22:55
 **/
public class ApplicationContext {

    private static final Logger logger = LoggerFactory.getLogger(ApplicationContext.class);

    private static final ThreadLocal<Map<String, Object>> WEB_SECURITY_HOLDER = InheritableThreadLocal.withInitial(HashMap::new);

    private static final String REQUEST_KEY = "web.request.key";

    private static final String RESPONSE_KEY = "web.response.key";

    private static Map<String, Object> CONFIG = new LinkedHashMap<>();

    private static Set<String> SESSION_KEYS = new ConcurrentSkipListSet<>();

    //应用是否启动标识
    private static boolean started = false;

    static {
        InputStream applicationConfigStream = ApplicationContext.class.getClassLoader()
                .getResourceAsStream("application.properties");
        Properties properties = new Properties();
        try {
            properties.load(applicationConfigStream);
        } catch (IOException e) {
            logger.error("加载配置[{}]失败", e);
        }
        initApplicationConfig(properties);
    }

    /**
     * 初始化应用的配置
     *
     * @param properties
     */
    public static synchronized void initApplicationConfig(Properties properties) {
        if (!started) {
            properties.forEach((key, value) -> {
                logger.info("web application load config {}:{}", key, value);
                CONFIG.put(Objects.toString(key), value);
            });
            started = true;
        } else {
            logger.warn("application is started!!!  exists config:{}", JSONUtil.toJSON(CONFIG));
        }
    }

    /**
     * 根据key从获取配置
     *
     * @param key    配置key
     * @param tClass 类型
     * @param <T>
     * @return
     */
    public static <T> T getApplicationConfigByKey(String key, Class<T> tClass) {
        return BeanUtil.convert(CONFIG.get(key), tClass);
    }


    /**
     * 根据key从获取配置
     *
     * @param key          配置key
     * @param tClass       返回值类型
     * @param defaultValue 默认值
     * @param <T>
     * @return
     */
    public static <T> T getApplicationConfigByKey(String key, Class<T> tClass, Object defaultValue) {
        return BeanUtil.convert(CONFIG.getOrDefault(key, defaultValue), tClass);
    }

    public static void setRequest(HttpServletRequest request) {
        WEB_SECURITY_HOLDER.get()
                .put(REQUEST_KEY, request);
    }

    public static void setResponse(HttpServletRequest request) {
        WEB_SECURITY_HOLDER.get()
                .put(RESPONSE_KEY, request);
    }

    /**
     * 获取当前请求的request
     *
     * @return
     */
    public static HttpServletRequest getRequest() {
        return (HttpServletRequest) WEB_SECURITY_HOLDER.get()
                .get(REQUEST_KEY);
    }


    /**
     * 获取当前请求的response
     *
     * @return
     */
    public static HttpServletResponse getResponse() {
        return (HttpServletResponse) WEB_SECURITY_HOLDER.get()
                .get(RESPONSE_KEY);
    }

    public static HttpSession getSession() {
        return getRequest().getSession();
    }

    /**
     * 清理当前ThreadLocal中缓存的数据
     */
    public static void clearHolder() {
        WEB_SECURITY_HOLDER.get()
                .clear();
        WEB_SECURITY_HOLDER.remove();
    }

    /**
     * 将值放到session中
     *
     * @param key
     * @param object
     */
    public static void putObject2Session(String key, Object object) {
        getSession().setAttribute(key, object);
    }

    /**
     * 将值session中移除
     *
     * @param key
     */
    public static void removeObject2Session(String key) {
        getSession().removeAttribute(key);
    }

    /**
     * 设置session过期
     */
    public static void clearSession() {
        getSession().invalidate();
    }

    /**
     * 从session中获取值
     *
     * @param key
     * @param <T>
     * @return
     */
    public static <T> T getObjectBySession(String key) {
        return (T) getSession().getAttribute(key);
    }

    /**
     * 当前登录的用户
     *
     * @param user
     */
    public static void putUser(User user) {
        putObject2Session(WebConstant.LOGIN_USER_KEY, user);
    }
}
